package com.samuel.blog.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.samuel.blog.bean.PageBean;
import com.samuel.blog.dao.ArticleDao;
import com.samuel.blog.dao.AuthorDao;
import com.samuel.blog.entity.ArticleEntity;
import com.samuel.blog.entity.AuthorEntity;
import com.samuel.blog.service.ArticleService;
import com.samuel.blog.utils.LuceneUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author kaiji
 */
@Service("articleService")
public class ArticleServiceImpl extends BaseServiceImpl<ArticleEntity, String> implements ArticleService {
	
	@Resource(name = "articleDao")
	ArticleDao articleDao;
	@Resource(name = "authorDao")
	AuthorDao authorDao;

	@Override
	@Transactional(readOnly = true)
	public List<ArticleEntity> getByAuthorId(String authorId) {
		Map<String, Object> artMap = new HashMap<>();
		artMap.put("authorId", authorId);
		List<ArticleEntity> selectByMap = articleDao.selectByMap(artMap);
		List<ArticleEntity> articles = Optional.ofNullable(selectByMap).orElse(new ArrayList<>());
		articles.forEach(article->{
			AuthorEntity author = authorDao.selectByPrimaryKey(article.getAuthorId());
			article.setAuthor(Optional.ofNullable(author).orElse(new AuthorEntity()));
		});
		
		return selectByMap;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean updateBatchById(List<ArticleEntity> articleList) {
		try {
			articleList.forEach(articleEntity->articleDao.updateByPrimaryKeySelective(articleEntity));
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public int insert(ArticleEntity article) {
		int num = articleDao.insert(article);
		if (num > 0) {
			//  缓存在Lucene中
			IndexWriter indexWriter = LuceneUtils.getIndexWriter();
			Document doc = new Document();
			doc.add(new StringField("title", article.getTitle(), Field.Store.YES));
			doc.add(new TextField("content", article.getContent(), Field.Store.YES));
			try {
				// 添加文档
				indexWriter.addDocument(doc);
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					if (null != indexWriter) {
						indexWriter.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return num;
	}

	@Override
	@Transactional(readOnly = true)
	public List<ArticleEntity> selectByTag(String tagId) {
		List<ArticleEntity> articleList = articleDao.selectByTag(tagId);
		return Optional.ofNullable(articleList).orElse(new ArrayList<>());
	}

	@Override
	@Transactional(readOnly = true)
	public PageInfo<ArticleEntity> selectPageByTag(PageBean pageBean, String tagId) {
		PageHelper.startPage(pageBean.getPageNum(), pageBean.getPageSize());
		List<ArticleEntity> list = articleDao.selectByTag(tagId);
		PageInfo<ArticleEntity> pageInfo = new PageInfo<>(list);
		return Optional.of(pageInfo).orElse(new PageInfo<>());
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int update(ArticleEntity article, List<String> tagIds) {
		int num = this.updateById(article);
		// 删除这个文章与标签的关系
		deleteArticleAndTagByArticleId(article.getArticleId());
		// 保存这个文章与标签的关系
		saveArticleAndTag(article.getArticleId(), tagIds);
		if (num > 0) {
			return num;
		} else {
			return 0;
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int save(ArticleEntity article, List<String> tagIds) {
		int num = this.insert(article);
		// 保存这个文章与标签的关系
		saveArticleAndTag(article.getArticleId(), tagIds);
		if (num > 0) {
			return num;
		} else {
			return 0;
		}
	}

	private void deleteArticleAndTagByArticleId(String articleId) {
		articleDao.deleteArticleAndTagByArticleId(articleId);
	}

	private void saveArticleAndTag(String articleId, List<String> tagIds) {
		Map<String, Object> filterMap = new HashMap<>();
		filterMap.put("articleId", articleId);
		tagIds.forEach(tagId->{
			filterMap.put("tagId", tagId);
			articleDao.saveArticleAndTag(filterMap);
		});
	}

}
